from fastapi import FastAPI, Request, status
from pathlib import Path
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.exceptions import RequestValidationError, HTTPException
from utils import logger

from fastapi.staticfiles import StaticFiles
from utils.response import Response
from dotenv import load_dotenv
import os
from starlette.requests import Request
from fastapi.responses import FileResponse
from contextlib import asynccontextmanager

# 导入路由
from views import auth_router, front_router, admin_router
from routes.auth.auth_routes import router as auth_api_router
from routes.admin.admin_routes import router as admin_api_router
from routes.front.chat_routes import router as front_api_router
from routes.user.user_routes import router as user_router

# 导入数据库连接和中间件
from models import init_db, close_db
from auth.middleware import auth_middleware, admin_middleware

from fastapi.middleware.cors import CORSMiddleware

load_dotenv()


# 应用生命周期管理
@asynccontextmanager
async def lifespan(app: FastAPI):
    init_db()
    logger.get_logger(__name__).info("数据库连接初始化完成")
    yield
    close_db()
    logger.get_logger(__name__).info("数据库连接已关闭")


log = logger.get_logger(__name__)
app = FastAPI(
    title="小菊问诊",
    description="一个基于FastApi的问诊系统",
    version="1.0.0",
    lifespan=lifespan
)

# 配置允许跨域的源
origins = [
    "http://localhost:5173",  # Vue 开发服务器
    "*"  # 允许所有
]
# 挂载中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,  # 允许的源
    allow_credentials=True,  # 是否允许携带 Cookie
    allow_methods=["*"],  # 允许所有 HTTP 方法
    allow_headers=["*"],  # 允许所有请求头
    allow_origin_regex="https?://.*",  # 允许所有协议和域名的正则表达式
    expose_headers=["Access-Control-Allow-Origin"]  # 暴露给浏览器的响应头
)

# 添加中间件
app.middleware("http")(auth_middleware)
app.middleware("http")(admin_middleware)

# 挂载静态文件
app.mount("/static", StaticFiles(directory="static"), name="static")
app.mount("/templates", StaticFiles(directory="templates"), name="templates")

# 注册路由 - 路由前缀已在views中定义
app.include_router(auth_router, tags=["认证"])
app.include_router(front_router, tags=["前端功能"])
app.include_router(admin_router, tags=["管理员功能"])

# 注册API路由
app.include_router(auth_api_router)
app.include_router(admin_api_router)
app.include_router(front_api_router)
app.include_router(user_router)


@app.get("/")
async def welcome(request: Request):
    """
    登录首页
    :return:
    """
    return FileResponse("templates/index.html")


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    """
    捕获参数校验异常返回
    :param request:
    :param exc:
    :return:
    """
    # 获取所有错误信息
    errors = exc.errors()
    # 提取第一个错误的详细信息
    first_error = errors[0] if errors else {}
    msg = first_error.get("msg", "参数校验失败")
    field = first_error.get("loc", [])
    
    detailed_msg = f"{msg}"
    if field:
        detailed_msg += f" (字段: {field[-1]})"
        
    return Response.error(
        code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        message=detailed_msg
    )


@app.exception_handler(404)
async def page_404(request: Request, exc):
    """
    404找不到页面
    :param request:
    :param exc:
    :return:
    """
    return Response.error(
        code=status.HTTP_404_NOT_FOUND,
        message="该接口不存在"
    )


@app.exception_handler(500)
async def page_500(request: Request, exc):
    """
    500服务器内部错误
    :param request:
    :param exc:
    :return:
    """
    import traceback
    log.error("Unhandled 500: %s", traceback.format_exc())
    return Response.error(code=status.HTTP_500_INTERNAL_SERVER_ERROR, message="服务器内部错误")


@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
    """
    处理所有HTTPException，统一转换为Response格式
    :param request:
    :param exc:
    :return:
    """
    return Response.error(
        code=exc.status_code,
        message=exc.detail if exc.detail else f"HTTP错误 {exc.status_code}"
    )


@app.exception_handler(403)
async def page_403(request: Request, exc):
    """
    403权限不足
    :param request:
    :param exc:
    :return:
    """
    return Response.error(code=status.HTTP_403_FORBIDDEN, message="权限不足")


#
@app.exception_handler(401)
async def page_401(request: Request, exc):
    """
    401未授权
    :param request:
    :param exc:
    :return:
    """
    return Response.error(code=status.HTTP_401_UNAUTHORIZED, message="未授权访问")


@app.exception_handler(405)
async def page_405(request: Request, exc):
    """
    405方法不被允许
    :param request:
    :param exc:
    :return:
    """
    return Response.error(code=status.HTTP_405_METHOD_NOT_ALLOWED, message="方法不被允许")


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="localhost", port=9870)
